package com.hk.commons.img;

import com.hk.commons.util.CollectionUtils;
import lombok.Data;
import lombok.experimental.Accessors;

import java.awt.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 文本 绘制
 *
 * @author Kevin
 */
@Data
@Accessors(chain = true)
public class TextCell implements MergeCell {

    private String text;

    private Color color = Color.WHITE;

    private Font font = FontUtil.YAHEI_PLAIN_20;

    private boolean enableLineBreak = true;

    private String suffix = "...";

    private int lineSpace;

    private int startX, startY;

    private int endX, endY;

    /**
     * 绘制样式
     */
    private ImgCreateOptions.DrawStyle drawStyle = ImgCreateOptions.DrawStyle.HORIZONTAL;

    private ImgCreateOptions.AlignStyle alignStyle = ImgCreateOptions.AlignStyle.LEFT;

    @Override
    public void draw(Graphics2D g2d) {
        g2d.setFont(font);
        g2d.setColor(color);
        var fontMetrics = FontUtil.getFontMetric(font);
        int tmpHeight = fontMetrics.getHeight(), tmpW = font.getSize() >>> 1;
        int tmpY = startY, tmpX = startX;
        var offsetX = drawStyle == ImgCreateOptions.DrawStyle.VERTICAL_LEFT
                ? (font.getSize() + fontMetrics.getDescent() + lineSpace)
                : -(font.getSize() + fontMetrics.getDescent() + lineSpace);
        var splitText = batchSplitText(this.text, fontMetrics);
        if (!enableLineBreak && CollectionUtils.isNotEmpty(splitText)) {
            String text = splitText.get(0);
            for (int i = 0, len = text.length(); i < len; i++) {
                splitText = batchSplitText(text.substring(0, len - i - 1) + suffix, fontMetrics);
                if (CollectionUtils.size(splitText) == 1) {
                    break;
                }
            }
        }
        for (var info : splitText) {
            if (drawStyle == ImgCreateOptions.DrawStyle.HORIZONTAL) {
                int calculateX = calculateX(info, fontMetrics);
                g2d.drawString(info, calculateX, tmpY);
                // 换行，y坐标递增一位
                tmpY += fontMetrics.getHeight() + lineSpace;
            } else {
                var chars = info.toCharArray();
                tmpY = calculateY(info, fontMetrics);
                for (int i = 0; i < chars.length; i++) {
                    tmpX = PunctuationUtil.isPunctuation(chars[i]) ? tmpW : 0;
                    g2d.drawString(chars[i] + "",
                            tmpX + (PunctuationUtil.isPunctuation(chars[i]) ? tmpW : 0),
                            tmpY);
                    tmpY += tmpHeight;
                }

                // 换一列
                tmpX += offsetX;
            }
        }
    }


    // 若单行文本超过长度限制，则自动进行换行
    private List<String> batchSplitText(String text, FontMetrics fontMetrics) {
        var ans = new ArrayList<String>();
        if (drawStyle == ImgCreateOptions.DrawStyle.HORIZONTAL) {
            var lineLen = Math.abs(endX - startX);
            ans.addAll(Arrays.asList(CalculateHelper.splitStr(text, lineLen, fontMetrics)));
        } else {
            var lineLen = Math.abs(endY - startY);
            ans.addAll(Arrays.asList(CalculateHelper.splitVerticalStr(text, lineLen, fontMetrics)));
        }
        return ans;
    }

    private int calculateX(String text, FontMetrics fontMetrics) {
        if (alignStyle == ImgCreateOptions.AlignStyle.LEFT) {
            return startX;
        } else if (alignStyle == ImgCreateOptions.AlignStyle.RIGHT) {
            return endX - fontMetrics.stringWidth(text);
        } else {
            return startX + ((endX - startX - fontMetrics.stringWidth(text)) >>> 1);
        }
    }

    private int calculateY(String text, FontMetrics fontMetrics) {
        if (alignStyle == ImgCreateOptions.AlignStyle.TOP) {
            return startY;
        } else if (alignStyle == ImgCreateOptions.AlignStyle.BOTTOM) {
            var size = fontMetrics.stringWidth(text) + fontMetrics.getDescent() * (text.length() - 1);
            return endY - size;
        } else {
            var size = fontMetrics.stringWidth(text) + fontMetrics.getDescent() * (text.length() - 1);
            return startY + ((endY - endX - size) >>> 1);
        }
    }
}
